''
'' Copyright (C) 2006 Ruben Rodriguez a.k.a. cha0s. ---> rubentbstk[AT]gmail.com
''
''	This software is provided 'as-is', without any express or implied warranty. 
''	In no event will the authors be held liable for any damages arising from 
''	the use of this software.
''	
''	Permission is granted to anyone to use this software for any purpose, 
''	including commercial applications, and to alter it and redistribute it 
''	freely, subject to the following restrictions:
''	
''	1. The origin of this software must not be misrepresented; you must not claim 
''	that you wrote the original software. If you use this software in a product, 
''	an acknowledgment in the product documentation would be appreciated but is 
''	not required.
''	
''	2. Altered source versions must be plainly marked as such, and must not be 
''	misrepresented as being the original software.
''	
''	3. This notice may not be removed or altered from any source 
''	distribution. 
''
''	4. Also, your soul. Your soul is mine. :)
''

#IfNDef __CHI_SOCKETS_BI__
#Define __CHI_SOCKETS_BI__

  #include "rawsock.bi"
  
  #libpath __path__
  #inclib "sock"
  
  #ifndef CR_LF
    
    const as string CR_LF = ( chr( 13, 10 ) )
    
  #endif
                               /' 128 KB '/
  const as integer BUFFERLEN = 128  *  1024
    
  namespace port
    
    /' Common port numbers '/
    const as integer HTTP = 80
    const as integer IRC  = 6667
    
  end namespace

  namespace sock                             
    
    type DGRAM_ID as longint
    #define makeDGRAM_ID(ip,port) ((clngint(ip) shl 32) or clngint(port))
    #define DGRAM_ID_ip(dgramid) (dgramid shr 32)
    #define DGRAM_ID_port(dgramid) (dgramid and &hffff)
    
    type transferBuffer
      
      /' Buffer data '/
      buff  as ubyte ptr
      
      /' Buffer size '/
      size  as integer
      
      declare constructor( )
      declare destructor( )
      
    end type
    
  
    type bare
      
      declare constructor( )
      declare destructor( )
        
        
      /' Public. '/ 
        
        /' Opening/closing socket connections '/
        
          declare function client( byref serverName as string, byval port       as integer ) as integer
          declare function server( byval port as integer ) as integer
          declare function UDPclient( byref serverName as string ) as integer
          declare function UDPserver( byval port as integer ) as integer

          declare function listen( byval timeout as double = 0 ) as integer                                    
          declare function listenToNew( byref thatSock as sock.bare, byval timeout as double = 0 ) as integer 

          declare sub close( )
          
        /' '/
        
        /' While connected '/
          
          /' Getting data '/
          
            /' Retrieve ( amount * len( returnValue ) ) bytes from 
               the socket into return value's address. '/
            declare function get( byref returnValue as byte   , byval amount as integer = 1, byref timeOut as double = 0.00001 ) as integer
            declare function get( byref returnValue as short  , byval amount as integer = 1, byref timeOut as double = 0.00001 ) as integer
            declare function get( byref returnValue as integer, byval amount as integer = 1, byref timeOut as double = 0.00001 ) as integer
            declare function get( byref returnValue as single , byval amount as integer = 1, byref timeOut as double = 0.00001 ) as integer
            declare function get( byref returnValue as double , byval amount as integer = 1, byref timeOut as double = 0.00001 ) as integer
            declare function get( byref returnValue as longint, byval amount as integer = 1, byref timeOut as double = 0.00001 ) as integer
            
            declare function getBlock( byref returnValue as byte   , byval amount as integer = 1 ) as integer
            declare function getBlock( byref returnValue as short  , byval amount as integer = 1 ) as integer
            declare function getBlock( byref returnValue as integer, byval amount as integer = 1 ) as integer
            declare function getBlock( byref returnValue as single , byval amount as integer = 1 ) as integer
            declare function getBlock( byref returnValue as double , byval amount as integer = 1 ) as integer
            declare function getBlock( byref returnValue as longint, byval amount as integer = 1 ) as integer
            
            /' Retrieve the entire contents of the socket into the string. '/
            declare function get( byref returnValue as string ) as integer
            declare function getBlock( byref returnValue as string, length_ as integer = -1 ) as integer
            
            declare function getFrom( byref wherefrom as DGRAM_ID, byref value as ubyte, byref len_ as integer ) as integer
            
            /' Get data until 'search' is found, or 'timeOut' seconds 
               have been waited without a new addition to the buffer. '/
            declare function getUntil( byref res as string         /' Accumulation buffer '/, _ 
                                       byref search as string = "" /' String to look for '/, _ 
                                       byval timeOut as double = 0 /' Timeout value, in seconds '/ ) as integer
                                       
            /' Get exactly one CRLF delimited line. '/
            declare function getLine( byref res as string ) as integer
  
            /' Flush out (delete) up to BUFFERLEN bytes of data from the buffer. '/
            declare sub flush( byval timeOut as double = 0.0001 )
            
          /' '/
          
          /' Putting data '/
          
            /' Send ( amount * len( sendValue ) ) bytes from 
               'sendValue's address to the socket. '/
            declare function put( byref sendValue as byte   , byval amount as integer = 1 ) as integer
            declare function put( byref sendValue as short  , byval amount as integer = 1 ) as integer
            declare function put( byref sendValue as integer, byval amount as integer = 1 ) as integer
            declare function put( byref sendValue as single , byval amount as integer = 1 ) as integer
            declare function put( byref sendValue as double , byval amount as integer = 1 ) as integer
            declare function put( byref sendValue as longint, byval amount as integer = 1 ) as integer
            
            /' Send the entire string to the socket. '/
            declare function put( byref returnValue as string ) as integer
            declare function putTo( byref value as ubyte, byval len_ as integer, byval whereto as DGRAM_ID ) as integer
            
            /' Send a string with a trailing CRLF (carriage return & linefeed) '/
            declare function putLine( byref message as string ) as integer
            
          /' '/
          
          #define sock_UDT(x) *cast( ubyte ptr, @x ), len( x )
    
        /' '/
        
        /' Status functions '/
        
          /' Socket can be read directly without blocking. '/
          declare function isReadable( ) as integer
          
          /' Socket connection lost/closed '/
          declare function isClosed( ) as integer
          
          /' Length of data in incoming buffer. '/
          declare function length( ) as integer
          
          /' Own IP '/
          declare function getHostIP( ) as uinteger
          declare function getHostIPString( ) as string
          
          /' Other connection's IP '/
          declare function getPeerIP( ) as uinteger
          declare function getPeerIPString( ) as string
          
          /' Network names '/
          declare function getHostName( ) as string
          declare function getPeerName( ) as string
  
          /' Get last transfer, in bytes '/
          declare function getLastMovement( ) as integer
          
          
          /' Clear out last error. '/
          declare sub      clearError( ) 
          
          /' Get last error. '/
          declare function getError( ) as string
          
        /' '/
        
      /' '/
      
'      private:
        
        enum SOCK_PROPERTIES
        
          PROP_NULL   = &h0
          PROP_TCP    = &h1
          PROP_UDP    = &h2
          PROP_SERVER = &h4
          PROP_CLIENT = &h8
        
        end enum
        
        recvbuff as transferBuffer
        sendbuff as transferBuffer
        
        declare function validateClient( byval res as integer ) as integer
        declare function validateServer( byval res as integer ) as integer
        declare function validateSocket( ) as integer

        declare function timedRecieve( byval flag as uinteger = 0, byval timeout as double = 0.0 ) as integer
        declare function timedSend( byval flag as uinteger = 0, byval timeout as double = 0.0 ) as integer

        /' Berkeley socket '/
        communicator as uinteger
        
        /' Error string '/
        errMsg as string
        
        /' Last transfer amount, in bytes '/
        lastMovement as integer
        
        sockprop as bare.SOCK_PROPERTIES
        
      /' '/
      
      
    end type
    
  
    type HTTP
      
      declare constructor( )
      declare constructor( byref serverName as string              /' Server to connect to '/, _ 
                           byref method     as string  = "GET"     /' GET, POST '/, _ 
                           byref postData   as string  = ""        /' Only used if the last arg is "POST" '/, _
                           byval portNum    as integer = port.HTTP /' Port to connect on '/ )

      declare destructor( )
        
      /' Public. '/ 
        
        /' Opening/closing socket connections '/
        
          /' Open an HTTP connection with 'serverName'. '/
          declare function open( byref serverName as string              /' Server to connect to '/, _ 
                                 byref method     as string  = "GET"     /' GET, POST '/, _ 
                                 byref postData   as string  = ""        /' Only used if the last arg is "POST" '/, _
                                 byval portNum    as integer = port.HTTP /' Port to connect on '/ ) as integer
    
          /' Close socket connection and null socket. '/
          declare sub close( )
          
        /' '/
        
        /' While connected '/
          
          /' Getting data '/
          
            /' Retrieve the entire contents of the socket into the string. '/
            declare function get( byref returnValue as string ) as integer
            
            /' Get data until 'search' is found, or 'timeOut' seconds 
               have been waited without a new addition to the buffer. '/
            declare function getUntil( byref res as string         /' Accumulation buffer '/, _ 
                                       byref search as string = "" /' String to look for '/, _ 
                                       byval timeOut as double = 0 /' Timeout value, in seconds '/ ) as integer
                                       
            /' Get exactly one CRLF delimited line. '/
            declare function getLine( byref res as string ) as integer
            
            /' Flush out (delete) up to BUFFERLEN bytes of data from the buffer. '/
            declare sub flush( byref timeOut as double = 0.0001 )
            
          /' '/
          
          /' Putting data '/
          
            /' Send the entire string to the socket. '/
            declare function put( byref returnValue as string ) as integer
            
            /' Send a string with a trailing CRLF (carriage return & linefeed) '/
            declare function putLine( byref message as string ) as integer
            
          /' '/
    
        /' '/
        
        /' Status functions '/
        
          /' Socket can be read directly without blocking. '/
          declare function isReadable( ) as integer
          
          /' Socket connection lost/closed '/
          declare function isClosed( ) as integer
          
          /' Length of data in incoming buffer. '/
          declare function length( ) as integer
          
          /' Own IP '/
          declare function getHostIP( ) as uinteger
          declare function getHostIPString( ) as string
          
          /' Other connection's IP '/
          declare function getPeerIP( ) as uinteger
          declare function getPeerIPString( ) as string
          
          /' Network names '/
          declare function getHostName( ) as string
          declare function getPeerName( ) as string
  
          /' Get last transfer, in bytes '/
          declare function getLastMovement( ) as integer
          
          
          /' Clear out last error. '/
          declare sub      clearError( ) 
          
          /' Get last error. '/
          declare function getError( ) as string
          
        /' '/
        
      /' '/
      
      private:
        
        socketInside as bare
      
    end type

    const as integer BUFFER_CHUNK = 256

    type IRC
      
      declare constructor( )
      declare constructor( byref serverName as string             /' Server to connect to '/, _ 
                           byref nickName   as string             /' Nickname '/, _ 
                           byref userName   as string             /' Username '/, _ 
                           byref passWord   as string  = ""       /' Password '/, _
                           byval thisPort   as integer = port.IRC /' Connect on port... '/ )
  
      declare destructor( )
        
      /' Public. '/ 
        
        /' Opening/closing socket connections: '/
        
          /' Open an IRC connection with 'serverName'. '/
          declare function open( byref serverName as string             /' Server to connect to '/, _ 
                                 byref nickName   as string             /' Nickname '/, _ 
                                 byref userName   as string             /' Username '/, _ 
                                 byref passWord   as string  = ""       /' Password '/, _
                                 byval thisPort   as integer = port.IRC /' Connect on port... '/ ) as integer
    
          /' Close socket connection and null socket. '/
          declare sub close( )
          
        /' '/
        
        /' While connected '/
        
          declare function joinChannel( byref toChannel as string ) as integer
          declare function partChannel( byref outChannel as string, byref partMessage as string = "..." ) as integer
          
          declare function ping( byref toWhom as string ) as integer
          declare function pong( byref toWhom as string ) as integer
          
          declare function sendMessage( byref toChannel as string, byref theMessage as string ) as integer
          declare function sendNotice( byref toChannel as string, byref theMessage as string ) as integer
          
          declare function channelUsers( byref chan as string ) as string
          declare function randomUser( byref chan as string, byval stripPriviledges as integer ) as string
          
          declare sub      changeNick( byref toNick as string )
          
          declare sub      quit( byref quitMessage as string = "..." )

          
          /' Getting data '/
          
            /' Get exactly one CRLF delimited line. '/
            declare function getLine( byref res as string ) as integer

            /' Flush out (delete) up to BUFFERLEN bytes of data from the buffer. '/
            declare sub flush( byref timeOut as double = 0.0001 )

          /' '/
          
          /' Putting data '/
          
            /' Send a string with a trailing CRLF (carriage return & linefeed) '/
            declare function putLine( byref message as string ) as integer
            
          /' '/
    
        /' '/
        
        /' Status functions '/
        
          /' Socket connection lost/closed '/
          declare function isClosed( ) as integer
          
          /' Own IP '/
          declare function getHostIP( ) as uinteger
          declare function getHostIPString( ) as string
          
          /' Other connection's IP '/
          declare function getPeerIP( ) as uinteger
          declare function getPeerIPString( ) as string
          
          /' Network names '/
          declare function getHostName( ) as string
          declare function getPeerName( ) as string
  
          /' Clear out last error. '/
          declare sub      clearError( ) 
          
          /' Get last error. '/
          declare function getError( ) as string
          
        /' '/
        
      /' '/

      private:
        
        socketInside as bare
        
        /' internal buffer '/
        
          buffer as string ptr
          bufferLoc as integer
          bufferLen as integer
          bufferSize as integer
          
          leftovers as string
          
          declare sub      fillReservoir( )
          declare function popElement( byref retString as string, byval idx as integer ) as integer
          declare sub      enlargeBuffer( byval newSize as integer )
        
        /' '/
        
        /' format parsing '/
        
          caret as integer
          currentTok as string
        
        /' '/

      /' '/
      
      
    end type

  end namespace

  namespace IRC

    enum colors
    
      White 
      Black 
      Blue 
      Green 
      Light_Red 
      Brown 
      Purple 
      Orange 
      Yellow 
      Light_Green 
      Cyan 
      Light_Cyan 
      Light_Blue 
      Pink 
      Grey 
      Light_Grey
      
    end enum
    
    type message
    
      declare destructor( )
      
      /' IRC Message prefix. '/
      prefix  as string

      /' IRC Message source. '/
      id      as string
      
      /' IRC Message source's host. '/
      host    as string
      
      /' IRC command. '/
      command as string
      
      /' Which param is the trailing/last '/
      trailing as integer
      
      /' Number of valid parameters. '/
      params      as integer

      /' Array of parameters. '/
      param( 15 ) as string
      
      /' Parse one line into this structure '/
      declare function parse( byref thisMessage as string ) as integer

    end type
    
    /' Make a line an IRC action '/
    declare function action( ByRef actionString as string ) as string
    
    /' Make a line bold. '/
    declare function bold( ByRef boldString as string ) as string
    
    declare function invert( ByRef thisString as string ) as string
    declare function underline( ByRef thisString as string ) as string

    declare function color( ByRef thisString as string, byval fgColor as integer = -1, byval bgColor as integer = -1 ) as string
    
    declare function rainbow( ByRef thisString as string ) as string
    

  end namespace

  
#EndIf '' __CHI_SOCKETS_BI__